package anet

import "fmt"

const (
	MsgType_Unknown MsgType = 999

	OK                  uint32 = 10000
	UnexpectedAppID     uint32 = 20001
	UnexpectedChannelID uint32 = 20002
	UnexpectedUserID    uint32 = 20003
	BadRequest          uint32 = 20004
	IllegalRequest      uint32 = 20005
	SessionNotExist     uint32 = 20006
	RequestDiscard      uint32 = 20007
	RequestTimeout      uint32 = 20008
)

// Generate Response for req
func Response(req *Msg, code uint32, data []byte) *Msg {
	msg := &Msg{
		Type:      req.Type,
		Code:      code,
		AppId:     req.AppId,
		ChannelId: req.ChannelId,
		UserId:    req.UserId,
		SerialId:  req.SerialId,
		Dst:       "",
		Data:      data,
	}

	return msg
}

// Generate A New Request
func Request(typ MsgType, appid, channelid, userid, dst, traceid string, data []byte) *Msg {
	msg := &Msg{
		Type:      typ,
		Code:      0,
		AppId:     appid,
		ChannelId: channelid,
		UserId:    userid,
		Dst:       dst,
		TraceId:   traceid,
		Data:      data,
	}

	return msg
}

// Duplicate from msg
func DupMsg(msg *Msg) *Msg {
	dup := &Msg{
		Type:      msg.Type,
		Code:      msg.Code,
		AppId:     msg.AppId,
		ChannelId: msg.ChannelId,
		UserId:    msg.UserId,
		Dst:       msg.Dst,
		SubType:   msg.SubType,
		Data:      msg.Data,
	}

	return dup
}

func ClosedMessage(appid, channelid, userid string) *Msg {
	msg := &Msg{
		Type:      MsgType_Closed,
		AppId:     appid,
		ChannelId: channelid,
		UserId:    userid,
	}

	return msg
}

func (m *Msg) Str() string {
	if m.Code != 0 {
		return fmt.Sprintf("%s_%d %s %s %s %d %s",
			m.Type.String(), m.Code, m.AppId, m.ChannelId, m.UserId, m.SerialId, m.TraceId)
	} else {
		return fmt.Sprintf("%s %s %s %s %d %s %d %s",
			m.Type.String(), m.AppId, m.ChannelId, m.UserId, m.SerialId, m.Dst, m.SubType, m.TraceId)
	}
}

func MsgTypeName(t string) MsgType {
	switch t {
	case "Join":
		return MsgType_Join
	case "Leave":
		return MsgType_Leave
	case "Message":
		return MsgType_Message
	case "Notify":
		return MsgType_Notify
	case "Closed":
		return MsgType_Closed
	case "Update":
		return MsgType_Update
	default:
		return MsgType_Unknown
	}
}
